#include <xp/utl/grep.h>
#include <xp/bas/sio.h>
#include <xp/bas/stdio.h>

struct file_t
{
	xp_sio_t* sio;
	const xp_char_t* name;
};

static xp_ssize_t input_file (
	int cmd, void* arg, xp_char_t* data, xp_size_t count)
{
	struct file_t* f = (struct file_t*)arg;
	
	if (cmd == XP_GREP_IO_OPEN) {
		f->sio = xp_sio_open (XP_NULL, f->name, XP_TEXT("r"));
		if (f->sio == XP_NULL) return -1;
		return 0;
	}

	if (cmd == XP_GREP_IO_CLOSE) {
		return xp_sio_close (f->sio);
	}

	if (cmd == XP_GREP_IO_DATA) {
		return xp_sio_getsx (f->sio, data, count);
	}

	return -1;
}

int xp_main (int argc, xp_char_t* argv[])
{
	xp_grep_t* grep;
	xp_grep_match_t match;
	int r = 0, n;

	if (argc != 3) {
		xp_fprintf (xp_stderr, 
			XP_TEXT("usage: %s string file\n"), argv[0]);
		return -1;
	}

	grep = xp_grep_open (XP_NULL);
	if (grep == XP_NULL) {
		xp_fprintf (xp_stderr, XP_TEXT("cannot instantiate grep\n"));
		return -1;
	}

	struct file_t f = { XP_NULL, argv[2] };
	if (xp_grep_attach_input (grep, input_file, &f) == -1) {
		xp_fprintf (xp_stderr, 
			XP_TEXT ("cannot attach input - %s\n"),
			xp_grep_errstr(grep));
		xp_grep_close (grep);
		return -1;
	}

	if (xp_grep_attach_matcher(
		grep, xp_grep_match_substr, argv[1]) == -1) {
		xp_fprintf (xp_stderr, 
			XP_TEXT ("cannot attach matcher - %s\n"),
			xp_grep_errstr(grep));
		xp_grep_close (grep);
		return -1;
	}

	while (1) {
		n = xp_grep_match (grep, &match);
		if (n == -1) {
			xp_fprintf (xp_stderr, 
				XP_TEXT("internal error - %s\n"),
				xp_grep_errstr(grep));
			r = -1;
			break;
		}
		if (n == 0) break;

		if (match.matched) {
			xp_printf (XP_TEXT("%ld %ld %s\n"),
				(long)match.line_num, (long)match.line_len, match.line);
		}
	}

	xp_grep_close (grep);
	return r;
}
